﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace NHibernate.Expression.Extensions.Utils {
    public class MemberPathExpressionVisitor : ExpressionVisitor {
        private IEnumerable<MemberExpression> memberAccesses;

        public IEnumerable<MemberExpression> MemberAccesses {
            get { return memberAccesses.Skip(1); }
        }

        public IEnumerable<KeyValuePair<object, MemberInfo>> MemberPath {
            get {
                foreach (var m in MemberAccesses) {
                    yield return MemberExpToObj(m);
                }
            }
        }

        public static KeyValuePair<object, MemberInfo> MemberExpToObj(MemberExpression exp) {
            var obj = System.Linq.Expressions.Expression.Lambda(exp.Expression).Compile().DynamicInvoke(null);
            return new KeyValuePair<object, MemberInfo>(obj, exp.Member);
        }

        public MemberPathExpressionVisitor(System.Linq.Expressions.Expression exp) {
            Visit(exp);
        }

        protected override System.Linq.Expressions.Expression VisitMemberAccess(MemberExpression m) {
            memberAccesses = memberAccesses.Prepend(m);
            return base.VisitMemberAccess(m);
        }
    }
}